package com.peycard.vista;

import java.io.IOException;
import java.io.Serializable;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import com.peycard.common.FinancialTransactionsDTO;
import com.peycard.service.BaseService;
import com.peycard.util.Constantes;
import com.peycard.util.Utils;

@Controller(Constantes.BEAN_TRANSACCIONES)
@Scope(Constantes.SCOPE_REQUEST)
public class TransaccionesControlador extends BaseController implements
		Serializable {

	private static final long serialVersionUID = 1L;
	private static Logger LOGGER = LoggerFactory
			.getLogger(TransaccionesControlador.class);
	private String buscarPan;
	private String buscarEstatus;
	private String buscarMonto;
	private Date buscarFecha;
	private String buscarNoAut;
	private String pattern;
	private String currentToken;
	private String username;
	private double latitude;
	private double longitude;
	private String idTransaction;
	private boolean isDisabled = false;
	public List<FinancialTransactionsDTO> listItems;
	public FinancialTransactionsDTO currentItem;

	public TransaccionesControlador() {
		pattern();
		currentToken = "TOKEN";// super.getTokenInContext();
		username = super.userLogged();
	}

	public String sendReceipt() {
		try {
			if (receiptISORequest(idTransaction)) {
				// TODO:Generar envío de email
			}
		} catch (IOException e) {
			super.addErrorMessage("No fue posible conectarse con el servidor.");
		} catch (ParseException e) {
			super.addWarningMessage("Ocurrió un error al parsear la petición.");
		}
		return "";
	}

	public String showReceipt() throws IOException {
		try {
			if (receiptISORequest(idTransaction)) {
				// TODO:Generar pdf
				String url = "pages/pdf";
				HttpServletRequest request = (HttpServletRequest) super
						.getFacesContext().getExternalContext().getRequest();
				request.setAttribute("tx", currentItem);
				String path = request.getContextPath();
				String basePath = request.getScheme() + "://"
						+ request.getServerName() + ":"
						+ request.getServerPort() + path + "/";
				LOGGER.debug("URL: " + basePath + url.toString());
				super.getFacesContext().getExternalContext()
						.redirect(basePath + url);
			}
		} catch (IOException e) {
			super.addErrorMessage("No fue posible conectarse con el servidor.");
		} catch (ParseException e) {
			super.addWarningMessage("Ocurrió un error al parsear la petición.");
		}
		return "";
	}

	private boolean receiptISORequest(String idTx) throws IOException,
			ParseException {
		BaseService service = new BaseService();
		service.setToken(currentToken);
		byte[] firma = service.signRequest(idTx);
		if (firma != null && firma.length > 0) {
			currentItem.setSign(firma);
			super.setTokenInContext(service.getToken());
		} else {
			super.addErrorMessage(service.getMessage());
			return false;
		}
		return true;
	}

	public String searchQuery() {
		if (buscarPan.isEmpty() && buscarEstatus.isEmpty()
				&& buscarMonto.isEmpty() && buscarFecha == null
				&& buscarNoAut.isEmpty()) {
			super.addInfoMessage("Debe especificar el criterio a buscar");
		} else {
			String data = null;
			try {
				BaseService service = new BaseService();
				service.setToken(currentToken);
				if (!buscarPan.isEmpty()) {
					String pan = "[" + buscarPan + "]";
					data = value(Constantes.FIND_BY_PAN, pan);
				} else if (!buscarEstatus.isEmpty()) {
					String estatus = "[" + buscarEstatus + "]";
					data = value(Constantes.FIND_BY_STATUS, estatus);
					service.transactionListISOMessage(data);
				} else if (!buscarMonto.isEmpty()) {
					String monto = "[" + buscarMonto + "]";
					data = value(Constantes.FIND_BY_AMOUNT, monto);
				} else if (buscarFecha != null) {
					String fecha = dateRange();
					data = value(Constantes.FIND_BY_DATE, fecha);
				} else if (!buscarNoAut.isEmpty()) {
					String noAut = "[" + buscarNoAut + "]";
					data = value(Constantes.FIND_BY_AUTH_NUM, noAut);
				}

				if (data != null) {
					service.transactionListISOMessage(data);

					if (service.getToken() != null) {
						super.setTokenInContext(service.getToken());
						list(service.getList());

					} else {
						super.addErrorMessage(service.getMessage());
					}
				}
				clearFields();
			} catch (IOException e) {
				super.addErrorMessage(Constantes.IOEXCEPTION_MESSAGE);
			} catch (ParseException e) {
				super.addErrorMessage(Constantes.PARSEEXCEPTION_MESSAGE);
			}
		}
		return "";
	}

	private void list(List<String> transactionList) {

		listItems = new ArrayList<FinancialTransactionsDTO>();

		for (int i = 0; i < transactionList.size(); i++) {
			String currentData = transactionList.get(i);
			List<String> txData = Utils.convertList(currentData);

			FinancialTransactionsDTO dto = new FinancialTransactionsDTO();
			long id = Long.valueOf(txData.get(0));
			dto.setIdFinancialTransactions(id);
			dto.setDateTimeTx(txData.get(3));
			dto.setStatus(txData.get(5));
			dto.setNoAut(txData.get(7));
			dto.setAmount(new BigDecimal(txData.get(8)));
			dto.setPan(txData.get(9));
			dto.setLatitude(Double.valueOf(txData.get(10)));
			dto.setLongitude(Double.valueOf(txData.get(11)));
			dto.setEmail(new Boolean(txData.get(12)));
			listItems.add(dto);
		}
		clearFields();
	}

	private String value(String type, String values) {
		List<Object> transList = new ArrayList<Object>();
		transList.add(type);
		transList.add(values);
		transList.add(username);
		return Utils.buildStringData(transList);
	}

	private String stringWithDateFormat(Date date) {
		SimpleDateFormat sdf = new SimpleDateFormat("MMddHHmmss");
		return sdf.format(date);
	}

	private String dateRange() {
		String startOfDay = stringWithDateFormat(buscarFecha);
		String endOfDay = stringWithDateFormat(endOfDay(buscarFecha));
		return "[" + startOfDay + "," + endOfDay + "]";
	}

	private Date endOfDay(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.set(Calendar.HOUR_OF_DAY, 23);
		calendar.set(Calendar.MINUTE, 59);
		calendar.set(Calendar.SECOND, 59);
		return calendar.getTime();
	}

	private void clearFields() {
		buscarPan = "";
		buscarEstatus = "";
		buscarMonto = "";
		buscarFecha = null;
		buscarNoAut = "";
	}

	public void pattern() {
		pattern = "dd/MM/yyyy";
	}

	public String getPattern() {
		return pattern;
	}

	public void setPattern(String pattern) {
		this.pattern = pattern;
	}

	public String getBuscarPan() {
		return buscarPan;
	}

	public void setBuscarPan(String buscarPan) {
		this.buscarPan = buscarPan;
	}

	public String getBuscarEstatus() {
		return buscarEstatus;
	}

	public void setBuscarEstatus(String buscarEstatus) {
		this.buscarEstatus = buscarEstatus;
	}

	public String getBuscarMonto() {
		return buscarMonto;
	}

	public void setBuscarMonto(String buscarMonto) {
		this.buscarMonto = buscarMonto;
	}

	public Date getBuscarFecha() {
		return buscarFecha;
	}

	public void setBuscarFecha(Date buscarFecha) {
		this.buscarFecha = buscarFecha;
	}

	public String getBuscarNoAut() {
		return buscarNoAut;
	}

	public void setBuscarNoAut(String buscarNoAut) {
		this.buscarNoAut = buscarNoAut;
	}

	public List<FinancialTransactionsDTO> getListItems() {
		return listItems;
	}

	public void setListItems(List<FinancialTransactionsDTO> listItems) {
		this.listItems = listItems;
	}

	public static long getSerialversionuid() {
		return serialVersionUID;
	}

	public FinancialTransactionsDTO getCurrentItem() {
		return currentItem;
	}

	public void setCurrentItem(FinancialTransactionsDTO currentItem) {
		idTransaction = String
				.valueOf(currentItem.getIdFinancialTransactions());
		this.currentItem = currentItem;
	}

	public boolean isDisabled() {
		return isDisabled;
	}

	public void setDisabled(boolean isDisabled) {
		this.isDisabled = isDisabled;
	}

	public static Logger getLOGGER() {
		return LOGGER;
	}

	public static void setLOGGER(Logger lOGGER) {
		LOGGER = lOGGER;
	}

	public String getCurrentToken() {
		return currentToken;
	}

	public void setCurrentToken(String currentToken) {
		this.currentToken = currentToken;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public double getLatitude() {
		return latitude;
	}

	public void setLatitude(double latitude) {
		this.latitude = latitude;
	}

	public double getLongitude() {
		return longitude;
	}

	public void setLongitude(double longitude) {
		this.longitude = longitude;
	}

	public String getIdTransaction() {
		return idTransaction;
	}

	public void setIdTransaction(String idTransaction) {
		this.idTransaction = idTransaction;
	}
}
